package com.bdk.middle.goods.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bdk.middle.common.domain.PageDO;
import com.bdk.middle.common.result.ResultDO;
import com.bdk.middle.common.status.ErrorCode;
import com.bdk.middle.common.util.BeanUtilsExtends;
import com.bdk.middle.common.util.Constant;
import com.bdk.middle.common.util.DateUtil;
import com.bdk.middle.common.util.SnowflakeIdWorker;
import com.bdk.middle.goods.api.client.GoodsClientApi;
import com.bdk.middle.goods.api.domain.*;
import com.bdk.middle.goods.api.query.GoodsQueryDO;
import com.bdk.middle.goods.core.entity.GoodsDetailEntity;
import com.bdk.middle.goods.core.entity.GoodsEntity;
import com.bdk.middle.goods.core.entity.GoodsImagesEntity;
import com.bdk.middle.goods.core.entity.GoodsTagEntity;
import com.bdk.middle.goods.core.mapper.GoodsDetailMapper;
import com.bdk.middle.goods.core.mapper.GoodsImagesMapper;
import com.bdk.middle.goods.core.mapper.GoodsMapper;
import com.bdk.middle.goods.core.mapper.GoodsTagMapper;
import com.bdk.middle.goods.service.GoodsService;
import com.bdk.middle.goods.service.SkuService;
import com.bdk.middle.goods.service.TagService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Reagan
 * @since 2021-03-18
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, GoodsEntity> implements GoodsService, GoodsClientApi {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsDetailMapper goodsDetailMapper;

    @Autowired
    private GoodsImagesMapper goodsImagesMapper;

    @Autowired
    private GoodsTagMapper goodsTagMapper;

    @Autowired
    private TagService tagService;

    @Autowired
    private SkuService skuService;

    @Override
    public ResultDO add(GoodsDO domain) {

        GoodsEntity entity = new GoodsEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        entity.setCreateDate(Calendar.getInstance().getTime());
        entity.setModifiDate(entity.getCreateDate());
        entity.setIsDelete(Constant.IS_DELETE_FALSE);
        entity.setStatus(Constant.OFF);
        entity.setGoodsNo(SnowflakeIdWorker.getId());
        int res = -1;
        try {
            res = goodsMapper.insert(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_ADD_ERROR.getCode() + " msg" + ErrorCode.GOODS_ADD_ERROR.getMsg());
            return result;
        }

        GoodsDetailDO detailDO = domain.getGoodsDetailDO();
        detailDO.setId(entity.getId());
        result = addDetail(detailDO);

        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        result = addImage(entity.getId(), domain.getGoodsImagesList());
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        result = addSku(entity.getId(), domain.getSkuList());
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        if(domain.getTagList() != null) {
            result = addGoodsTage(entity.getId(), domain.getTagList());
        }
        return result;
    }

    private ResultDO addSku(String goodsId, List<SkuDO> list) {
        ResultDO result = new ResultDO();
        for(SkuDO domain : list) {
            domain.setGoodsId(goodsId);
            result = skuService.add(domain);
            if(!result.isSuccess()) {
                return result;
            }
        }
        return result;
    }

    private ResultDO addGoodsTage(String goodsId, List<TagDO> list) {

        ResultDO result = new ResultDO();

        for(TagDO domain : list) {

            GoodsTagEntity entity = new GoodsTagEntity();
            result = tagService.add(domain);

            if(!result.isSuccess()) {
                return result;
            }

            entity.setGoodsId(goodsId);
            entity.setTagId((String) result.getModel(ResultDO.FIRST_MODEL_KEY));
            int res = -1;

            try {
                res = goodsTagMapper.insert(entity);
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }
        }

        return result;
    }

    private ResultDO addDetail(GoodsDetailDO domain) {

        GoodsDetailEntity entity = new GoodsDetailEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        int res = -1;
        try {
            res = goodsDetailMapper.insert(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_DETAIL_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_DETAIL_ADD_ERROR.getCode() + " msg" + ErrorCode.GOODS_DETAIL_ADD_ERROR.getMsg());
            return result;
        }

        return result;
    }


    @Override
    public ResultDO edit(GoodsDO domain) {

        GoodsEntity entity = new GoodsEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        entity.setModifiDate(Calendar.getInstance().getTime());
        int res = -1;
        try {
            res = goodsMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_EDIT_ERROR.getCode() + " msg" + ErrorCode.GOODS_EDIT_ERROR.getMsg());
            return result;
        }

        GoodsDetailDO detailDO = domain.getGoodsDetailDO();
        detailDO.setId(entity.getId());
        result = editDetail(detailDO);

        if(!result.isSuccess()) {
            return result;
        }

        if(domain.getGoodsImagesList().size() != 0) {
            result = deleteImage(domain.getId());
            if(!result.isSuccess()) {
                return result;
            }
            result = addImage(domain.getId(), domain.getGoodsImagesList());
        }

        return result;
    }

    public ResultDO editDetail(GoodsDetailDO domain) {

        GoodsDetailEntity entity = new GoodsDetailEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        int res = -1;
        try {
            res = goodsDetailMapper.updateById(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_DETAIL_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_DETAIL_EDIT_ERROR.getCode() + " msg" + ErrorCode.GOODS_DETAIL_EDIT_ERROR.getMsg());
            return result;
        }

        return result;
    }

    @Override
    public ResultDO get(String id) {

        ResultDO result = new ResultDO();
        GoodsEntity entity = null;

        try {
            entity = goodsMapper.selectById(id);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        GoodsDO domain = getDomain(entity);
        result = getDetail(id);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        domain.setGoodsDetailDO((GoodsDetailDO) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result = getImage(id);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        domain.setGoodsImagesList((List<GoodsImagesDO>) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result = getTag(id);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        domain.setTagList((List<TagDO>) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result = skuService.listByGoodsId(id);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        domain.setSkuList((List<SkuDO>) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);
        return result;
    }

    private ResultDO getTag(String goodsId) {
        ResultDO result = new ResultDO();
        List<GoodsTagEntity> list = null;
        try {
            list = goodsTagMapper.selectList(Wrappers.<GoodsTagEntity>lambdaQuery().eq(GoodsTagEntity::getGoodsId, goodsId));
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        List<TagDO> doList = new ArrayList<>();
        list.stream().forEach(entity-> {
            ResultDO res = tagService.get(entity.getTagId());
            doList.add((TagDO) res.getModel(ResultDO.FIRST_MODEL_KEY));
        });

        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    private ResultDO getDetail(String id) {

        ResultDO result = new ResultDO();
        GoodsDetailEntity entity = null;

        try {
            entity = goodsDetailMapper.selectById(id);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        GoodsDetailDO domain = getDetailDomain(entity);
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }

    @Override
    public ResultDO remove(String id, String modifier) {

        ResultDO result = new ResultDO();

        GoodsEntity entity = new GoodsEntity();

        entity.setId(id);
        entity.setIsDelete(Constant.IS_DELETE);
        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);

        int res = -1;
        try {
            res = goodsMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_DELETE_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_DELETE_ERROR.getCode() + " msg" + ErrorCode.GOODS_DELETE_ERROR.getMsg());
            return result;
        }
        result = skuService.removeByGoodsId(id, modifier);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        result = deleteImage(id);

        return result;
    }

    @Override
    public ResultDO find(GoodsQueryDO query) {

        ResultDO result = new ResultDO();

        QueryWrapper<GoodsEntity> wrapper = new QueryWrapper<>();

        if(StringUtils.isNotEmpty(query.getAppId())) {
            wrapper.eq("app_id", query.getAppId());
        }
        if(StringUtils.isNotEmpty(query.getBrandId())) {
            wrapper.eq("brand_id", query.getBrandId());
        }
        if(StringUtils.isNotEmpty(query.getMerchantId())) {
            wrapper.eq("merchant_id", query.getMerchantId());
        }
        if(StringUtils.isNotEmpty(query.getGoodsNo())) {
            wrapper.eq("goods_no", query.getGoodsNo());
        }
        if(StringUtils.isNotEmpty(query.getName())) {
            wrapper.like("name", query.getName());
        }
        if(query.getIsBean() != null) {
            wrapper.eq("is_bean", query.getIsBean());
        }
        if(query.getIsCoin() != null) {
            wrapper.eq("is_coin", query.getIsCoin());
        }
        if(query.getSupplyMethod() != null) {
            wrapper.eq("supply_method", query.getSupplyMethod());
        }
        if(query.getStatus() != null) {
            wrapper.eq("status", query.getStatus());
        }

        wrapper.eq("is_delete", Constant.IS_DELETE_FALSE);

        Page<GoodsEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        IPage<GoodsEntity> iPage = null;
        try {
            iPage = goodsMapper.selectPage(page, wrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<GoodsDO> doList = getDomainList(iPage.getRecords());

        PageDO<GoodsDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }

    private ResultDO addImage(String goodsId, List<GoodsImagesDO> doList) {

        ResultDO result = new ResultDO();

        for(GoodsImagesDO domain : doList) {
            GoodsImagesEntity entity = new GoodsImagesEntity();
            result = BeanUtilsExtends.copy(entity, domain);
            int res = -1;
            entity.setGoodsId(goodsId);
            try {
                res = goodsImagesMapper.insert(entity);
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }

            //判断r的值是否小于0.如果小于0 就代表添加失败
            if(res < 0) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.GOODS_IMAGE_ADD_ERROR);
                logger.debug("error code：" + ErrorCode.GOODS_IMAGE_ADD_ERROR.getCode() + " msg" + ErrorCode.GOODS_IMAGE_ADD_ERROR.getMsg());
                return result;
            }
        }
        return result;
    }

    private ResultDO deleteImage(String goodsId) {

        ResultDO result = new ResultDO();

        int res = -1;
        try {
            res = goodsImagesMapper.delete(Wrappers.<GoodsImagesEntity>lambdaQuery().eq(GoodsImagesEntity::getGoodsId, goodsId));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_IMAGE_DELETE_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_IMAGE_DELETE_ERROR.getCode() + " msg" + ErrorCode.GOODS_IMAGE_DELETE_ERROR.getMsg());
            return result;
        }

        return result;
    }

    private ResultDO getImage(String goodsId) {

        ResultDO result = new ResultDO();

        List<GoodsImagesEntity> list = null;
        try {
            list = goodsImagesMapper.selectList(Wrappers.<GoodsImagesEntity>lambdaQuery().eq(GoodsImagesEntity::getGoodsId, goodsId));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<GoodsImagesDO> doList = getDomainImagesList(list);
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    private GoodsDO getDomain(GoodsEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        GoodsDO domain = new GoodsDO();
        DateUtil.dateToString(entity.getCreateDate(), DateUtil.DATE_FORMAT);
        DateUtil.dateToString(entity.getModifiDate(), DateUtil.DATE_FORMAT);
        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }


    private List<GoodsDO> getDomainList(List<GoodsEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<GoodsDO> doList = new ArrayList<>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(GoodsEntity entity : list) {

                GoodsDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }

    private GoodsDetailDO getDetailDomain(GoodsDetailEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        GoodsDetailDO domain = new GoodsDetailDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private GoodsImagesDO getDomainImages(GoodsImagesEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        GoodsImagesDO domain = new GoodsImagesDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }


    private List<GoodsImagesDO> getDomainImagesList(List<GoodsImagesEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<GoodsImagesDO> doList = new ArrayList<>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(GoodsImagesEntity entity : list) {

                GoodsImagesDO domain = this.getDomainImages(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }


}
